Repository Public
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// /api/admin/submissions/[id]/reply — réponse au demandeur depuis le panel.3// Le message est D'ABORD écrit en base (source de vérité), puis envoyé par4// courriel (Resend) ; l'échec d'envoi est signalé mais le message reste.5// Pose first_response_at (délai de première réponse du dashboard).6import { NextRequest, NextResponse } from "next/server";7import {8 findSubmissionById,9 insertMessage,10 logEvent,11 touchFirstResponse,12} from "@/lib/comms/db";13import { getAdminSession, canViewSubmission } from "@/lib/comms/admin-auth";14import { sendAdminReply } from "@/lib/comms/receipt-email";1516export async function POST(17 req: NextRequest,18 { params }: { params: Promise<{ id: string }> },19) {20 const session = await getAdminSession();21 if (!session)22 return NextResponse.json({ error: "Non autorisé." }, { status: 401 });23 const id = Number((await params).id);24 const sub = Number.isInteger(id) ? findSubmissionById(id) : undefined;25 if (!sub || !canViewSubmission(session, sub))26 return NextResponse.json({ error: "Demande introuvable." }, { status: 404 });2728 const body = (await req.json().catch(() => null)) as { body?: string } | null;29 const text = (body?.body ?? "").trim().slice(0, 12000);30 if (!text)31 return NextResponse.json({ error: "Message vide." }, { status: 422 });32 if (!sub.email)33 return NextResponse.json(34 { error: "Cette demande n'a pas de courriel (soumission anonyme) — utilisez une note interne." },35 { status: 422 },36 );3738 insertMessage({39 submission_id: sub.id,40 sender_type: "admin",41 sender_admin_id: session.id,42 body: text,43 channel: "email",44 });45 touchFirstResponse(sub.id);46 logEvent(sub.id, session.id, "reponse", "Réponse envoyée au demandeur");4748 let sent = true;49 try {50 await sendAdminReply({51 to: sub.email,52 name: [sub.first_name, sub.last_name].filter(Boolean).join(" ") || "bonjour",53 reference: sub.reference,54 body: text,55 });56 } catch (e) {57 sent = false;58 console.error("[admin/reply] Resend :", (e as Error).message);59 }60 return NextResponse.json({ ok: true, sent });61}62